/*
	IAP flash programming
*/

#include "defines.h"

U32 param_table[5];
U32 result_table[5];



void _iap_entry(uint32_t param_tab[],uint32_t result_tab[])
{
    void (*iap)(uint32_t [],uint32_t []);

    iap = (void (*)(uint32_t [],uint32_t []))IAP_ADDRESS;
    iap(param_tab,result_tab);
}


/*
	Прыгаем на приложение
*/
__asm void boot_jump( uint32_t address )
{
   LDR SP, [R0]		;Load new stack pointer address
   LDR PC, [R0, #4]	;Load new program counter address
}
void execute_user_code(void)
{
	/* Change the Vector Table to the USER_FLASH_START 
	in case the user application uses interrupts */
	SCB->VTOR = USER_FLASH_START & 0x1FFFFF80;
	boot_jump(USER_FLASH_START);
}

void erase_sector(uint32_t start_sector,uint32_t end_sector)
{
  uint32_t interrupts;
  disable_interrupts(interrupts);
  
	param_table[0] = ERASE_SECTOR;
  param_table[1] = start_sector;
  param_table[2] = end_sector;
  param_table[3] = SystemFrequency/1000;
  _iap_entry(param_table,result_table);
	enable_interrupts(interrupts);
}

void prepare_sector(uint32_t start_sector,uint32_t end_sector)
{
	uint32_t interrupts;
  disable_interrupts(interrupts);
	param_table[0] = PREPARE_SECTOR_FOR_WRITE;
  param_table[1] = start_sector;
  param_table[2] = end_sector;
  param_table[3] = SystemFrequency/1000;
  _iap_entry(param_table,result_table);
	enable_interrupts(interrupts);
}

void write_data(uint32_t flash_address,uint32_t * flash_data_buf, uint32_t count)
{
    uint32_t interrupts;

		disable_interrupts(interrupts);
    param_table[0] = COPY_RAM_TO_FLASH;
    param_table[1] = flash_address;
    param_table[2] = (uint32_t)flash_data_buf;
    param_table[3] = count;
    param_table[4] = SystemFrequency/1000;
    _iap_entry(param_table,result_table);
		enable_interrupts(interrupts);
}

void enable_interrupts(uint32_t interrupts)
{
    __enable_irq();
}

void disable_interrupts(uint32_t interrupts)
{
    __disable_irq();
}
/*
	Проверяем корректность приложения
*/
int check_app()
{
	AppInfoT * info = (AppInfoT *)APP_INFO_ADDRESS;
	
	//А может все пусто?
	if (((*info).length==0xFFFFFFFF)||((*info).length==0))
		return 0;
	//Высчитываем CRC и проверяем с записанной
	if (crc32((U8 *)USER_FLASH_START,(*info).length)==(*info).crc32)
		return 1;
	else 
		return 0;
	
}

/*
	Высчитываем CRC32...ну или что то вроде этого
*/
U32 crc32(U8 * buffer, U32 length)
{
	U32 i;
	U32 result=0;
	for (i=0;i<length;i++)
		result += buffer[i];
	
	return result;
}
